package com.credithc.signature.core.service.signprovide.lanmao;

import com.alibaba.fastjson.JSONArray;
import com.cfca.ra.cs.generated.CertApplyVO;
import com.credithc.signature.common.mapper.SignatureLogMapper;
import com.credithc.signature.common.po.OfficialSealTemplate;
import com.credithc.signature.common.po.SealInfo;
import com.credithc.signature.common.po.SignatureLog;
import com.credithc.signature.common.po.Template;
import com.credithc.signature.common.ro.core.CoreRequet;
import com.credithc.signature.common.service.OfficialSealTemplateService;
import com.credithc.signature.common.service.SealInfoService;
import com.credithc.signature.common.service.SignatureLogService;
import com.credithc.signature.common.service.TemplateService;
import com.credithc.signature.common.service.lanmao.LanmaoFileService;
import com.credithc.signature.common.service.lanmao.LanmaoRegisterService;
import com.credithc.signature.common.service.lanmao.LanmaoSignService;
import com.credithc.signature.common.to.CFCASignTO;
import com.credithc.signature.common.utils.DateUtil;
import com.credithc.signature.common.utils.MessageFilterUtil;
import com.credithc.signature.core.constant.Constant;
import com.credithc.signature.core.service.SignatureService;
import com.credithc.signature.core.service.signprovide.SignatureProvider;
import com.credithc.signature.core.util.PathUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @desc: 懒猫签章实现类<br />
 * @author: Jingbo Hu<br/>
 * @time：2020年07⽉01⽇<br/>
 * @version：v1.0.0<br>
 */
@Slf4j
@Service("lanmaoSignature")
public class LanmaoProvider implements SignatureProvider {

    @Value("${signature.snapSignPdf.path}")
    String snapPDFPath;

    @Value("${signature.maxBatchSignNum:160}")
    Integer maxBatchSignNum;

    @Autowired
    LanmaoFileService lanmaoFileService;

    @Autowired
    LanmaoRegisterService lanmaoRegisterService;

    @Autowired
    LanmaoSignService lanmaoSignService;

    @Autowired
    SignatureLogMapper signatureLogMapper;

    @Autowired
    TemplateService templateService;

    @Autowired
    SignatureService signatureService;

    @Autowired
    SignatureLogService signatureLogService;

    @Autowired
    SealInfoService sealInfoService;

    @Autowired
    OfficialSealTemplateService officialSealTemplateService;


    @Override
    public String processSignature(CoreRequet coreRequet, String noSignPdfPath, List<Map<String, String>> certInfos, List<String> sealCodes) throws Exception {

        String signSnapPDFPath = null;

        try {
            //更新签章记录表为懒猫
            Example se = new Example(SignatureLog.class);
            Example.Criteria sec = se.createCriteria();
            SignatureLog signatureLog = new SignatureLog();
            sec.andEqualTo("requestSn", coreRequet.getRequestSn());
            signatureLog.setThirdPartyChannel(1);
            log.info("{}更新签章记录为懒猫", coreRequet.getRequestSn());
            sec.andLessThanOrEqualTo("createTime", DateUtil.getNextDate(1));
            sec.andGreaterThanOrEqualTo("createTime", DateUtil.getBeforeDate(2));
            signatureLogMapper.updateByExampleSelective(signatureLog, se);

            // 获取要签章pdf文件路径
            File file = new File(noSignPdfPath);
            String date = file.getParentFile().getName();
            String signPdfName = Constant.SNAP_PDF_PREFIX + coreRequet.getRequestSn() + Constant.PDF_EXT;
            signSnapPDFPath = PathUtil.getSignSnapPDFPath(snapPDFPath, signPdfName, date);
            log.info("{}签章文件路径为{}", coreRequet.getRequestSn(), signSnapPDFPath);
            Template template = templateService.selectByTemplateNo(coreRequet.getTemplateNo());
            Integer sealType = template.getSealType();
            String upUserId = getUpUserId(certInfos, sealCodes, sealType, coreRequet);
            log.info("{}获取单个用户id用于上传文件 -----{}", coreRequet.getRequestSn(), upUserId);
            //上传合同到存储引擎
            String fileId = lanmaoFileService.contractUpload(upUserId, noSignPdfPath, signPdfName, template.getTemplateName());
            log.info("{}文件上传成功 ---fileId为{}", coreRequet.getRequestSn(), fileId);
            JSONArray parm = new JSONArray();
            //封装公章参数
            List<SealInfo> sealInfos = new ArrayList<>();
            if (Constant.OFFICAL.equals(sealType) || Constant.OFFICAL_PERSONAL.equals(sealType)) {
                sealInfos = getSealInfos(coreRequet.getRequestSn(), coreRequet.getTemplateNo(), sealCodes);
                parm = lanmaoSignService.bulidEntKeyWordParm(parm, sealInfos);
                log.info("{}公章参数封装完成为", coreRequet.getRequestSn(), parm);
            }

            //封装私章参数 并签章
            if (Constant.PERSONAL.equals(sealType) || Constant.OFFICAL_PERSONAL.equals(sealType)) {
                List<Object> temp = new ArrayList<>();
                temp.addAll(certInfos);
                JSONArray jsonArray = new JSONArray(temp);
                List<CertApplyVO> certApplyVOList = jsonArray.toJavaList(CertApplyVO.class);
                signatureLogService.updateSealNum(coreRequet.getRequestSn(), certInfos.size(), sealInfos.size());
                //私章量太多 分批签
                if (certApplyVOList.size() > maxBatchSignNum) {
                    int totalSealNum = certApplyVOList.size();
                    int loopNum = (totalSealNum % maxBatchSignNum == 0) ? totalSealNum / maxBatchSignNum : totalSealNum / maxBatchSignNum + 1;
                    log.info("－消息－:requestSn={},分批处理签章,签章数据总量:{},最大盖章数为:{},分{}次盖完", coreRequet.getRequestSn(), totalSealNum, maxBatchSignNum, loopNum);
                    for (int index = 0; index < loopNum; index++) {
                        int startIndex = index * maxBatchSignNum;
                        int endIndex = (index + 1) * maxBatchSignNum > totalSealNum ? totalSealNum : (index + 1) * maxBatchSignNum;
                        lanmaoSignService.bulidPersonKeyWordParm(parm, certApplyVOList.subList(startIndex, endIndex));
                        log.info("{}开始签章{}", coreRequet.getRequestSn(), parm);
                        lanmaoSignService.keyWordSign(fileId, parm);
                        parm.clear();
                    }
                    log.info("－消息－:requestSn={},分批处理个人签章完成", coreRequet.getRequestSn());
                } else {
                    parm = lanmaoSignService.bulidPersonKeyWordParm(parm, certApplyVOList);
                    log.info("{}开始签章{}", coreRequet.getRequestSn(), parm);
                    lanmaoSignService.keyWordSign(fileId, parm);
                }
            } else {
                //仅公章签章
                signatureLogService.updateSealNum(coreRequet.getRequestSn(), 0, sealInfos.size());
                log.info("{}开始签章{}", coreRequet.getRequestSn(), parm);
                lanmaoSignService.keyWordSign(fileId, parm);
            }

            //锁定
            lanmaoSignService.contactLock(fileId);
            //下载文档
            lanmaoFileService.contactDownload(fileId, signSnapPDFPath);
        } catch (Exception e) {
            String errorMsg = MessageFilterUtil.limitLength(e.getMessage());
            signatureLogService.updateResult(errorMsg, coreRequet.getRequestSn());
            throw new RuntimeException(e);
        }
        signatureLogService.updateResult("签章成功", coreRequet.getRequestSn());
        return signSnapPDFPath;
    }

    /**
     * 获取公章信息
     *
     * @param requestSn
     * @param templateNo
     * @param sealCodes
     * @return
     * @throws Exception
     */
    private List<SealInfo> getSealInfos(String requestSn, String templateNo, List<String> sealCodes) throws Exception {
        if (sealCodes == null) {
            OfficialSealTemplate officialSealTemplate = new OfficialSealTemplate();
            officialSealTemplate.setTemplateNo(templateNo);
            List<OfficialSealTemplate> officialSealTemplates = officialSealTemplateService.selectByExample(officialSealTemplate);
            if (officialSealTemplates == null || officialSealTemplates.size() == 0) {
                log.error("－消息－:requestSn={},签章公章出现异常,该模板没有公章", requestSn);
                throw new Exception("模板没有公章");
            }
            List<String> sealCodeList = officialSealTemplates.stream().map(sealTemplate -> sealTemplate.getOfficialSealCode()).
                    collect(Collectors.toList());

            return sealInfoService.selectBySealCodeList(sealCodeList);
        } else if (sealCodes.isEmpty()) {
            return new ArrayList<>();
        } else {
            return sealInfoService.selectBySealCodeList(sealCodes);
        }
    }

    /**
     * 获取任意一个签章用户的懒猫id (懒猫接口必填项)
     *
     * @param certInfos
     * @param sealCodes
     * @param sealType
     * @param coreRequet
     * @return
     * @throws Exception
     */
    private String getUpUserId(List<Map<String, String>> certInfos, List<String> sealCodes, Integer sealType, CoreRequet coreRequet) throws Exception {
        if (sealType.equals(Constant.PERSONAL) || sealType.equals(Constant.OFFICAL_PERSONAL)) {
            List<Object> temp = new ArrayList<>();
            temp.addAll(certInfos);
            JSONArray jsonArray = new JSONArray(temp);
            List<CertApplyVO> certApplyVOList = jsonArray.toJavaList(CertApplyVO.class);
            CertApplyVO certApplyVO = certApplyVOList.get(0);
            return lanmaoRegisterService.registerPerson(certApplyVO.getUserName(), certApplyVO.getUserIdNo(), certApplyVO.getIdTypeCode());
        } else {
            List<CFCASignTO> officalSealInfoList = signatureService.getOfficialSealInfoList(coreRequet.getRequestSn(), coreRequet.getTemplateNo(), sealCodes);
            if (officalSealInfoList != null && !officalSealInfoList.isEmpty()) {
                return lanmaoRegisterService.registerEnt(officalSealInfoList.get(0).getSealCode());
            }
        }
        return "";
    }
}
